; TaskSwitch.asm
; contains the code for the TaskSwitch function.

; switches stacks and restores the execution state from the stack, before returning
; to whatever was executing

.code

ASMTaskSwitch proc
	; rcx = current task stack RSP
	; rdx = task to load stack RSP

	; save GP registers
	push	r12
	push	r13
	push	r14
	push	r15
	push	rdi
	push	rsi
	push	rbx
	push	rbp

	; save XMM registers
	sub		rsp, 168		; space for 10 xmm registers (xmm6:xmm15) and the MXCSR
	movdqu	xmmword ptr [rsp + 152], xmm6
	movdqu	xmmword ptr [rsp + 136], xmm7
	movdqu	xmmword ptr [rsp + 120], xmm8
	movdqu	xmmword ptr [rsp + 104], xmm9
	movdqu	xmmword ptr [rsp + 88], xmm10
	movdqu	xmmword ptr [rsp + 72], xmm11
	movdqu	xmmword ptr [rsp + 56], xmm12
	movdqu	xmmword ptr [rsp + 40], xmm13
	movdqu	xmmword ptr [rsp + 24], xmm14
	movdqu	xmmword ptr [rsp + 8], xmm15
	stmxcsr dword ptr [rsp]

	; save rsp to current task's stack
	mov		qword ptr [rcx], rsp

	; swap to the new task's rsp
	mov		rsp, qword ptr [rdx]

	; restore entity action execution state
	ldmxcsr	dword ptr [rsp]
	movdqu	xmmword ptr [rsp + 8], xmm15
	movdqu	xmmword ptr [rsp + 24], xmm14
	movdqu	xmmword ptr [rsp + 40], xmm13
	movdqu	xmmword ptr [rsp + 56], xmm12
	movdqu	xmmword ptr [rsp + 72], xmm11
	movdqu	xmmword ptr [rsp + 88], xmm10
	movdqu	xmmword ptr [rsp + 104], xmm9
	movdqu	xmmword ptr [rsp + 120], xmm8
	movdqu	xmmword ptr [rsp + 136], xmm7
	movdqu	xmmword ptr [rsp + 152], xmm6
	add		rsp, 168

	; restore general purpose registers
	pop		rbp
	pop		rbx
	pop		rsi
	pop		rdi
	pop		r15
	pop		r14
	pop		r13
	pop		r12

	; finished
	; return to whatever was executing previously
	ret

ASMTaskSwitch endp

end